﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Testing.DataService;
using Testing.DataService.Entities;
using Testing.DataService.Mock;
using Testing.DataService.Repositories;
using Testing.DataService.Repositories.Interfaces;
using Testing.IntegrationTests.Filters;
using System.Data.Entity.Repository.Filters;

namespace Testing.IntegrationTests
{
    [TestClass]
    public class UnitTestProduct
    {
        private IProductRepository _productRepository;

        [TestInitialize]
        public void TestInitialize()
        {
            _productRepository = new ProductRepository();
        }

        /// <summary>
        /// Add a product to the db this will test the entity configuration
        /// </summary>
        [TestMethod]
        public void IntegrationTest_Transaction_AddProduct()
        {
            bool result = false;

            RegisterableFilter filter = new RegisterableFilter
            {
                FilterInstance = new ProductFilterDuvelGreen2(),
                ParameterBag = null
            };
            QueryableFilterManager.Register(filter);

            Product product = new MockProduct()
                .CreateSingleProduct();

            result = _productRepository.AddProduct(product);

            Assert.IsTrue(result);
        }

        /// <summary>
        /// This will fillter duvel green 2 so only 0 and 1 are inserted in the db.
        /// </summary>
        [TestMethod]
        public void IntegrationTest_Transaction_AddEntitiesWithFilter()
        {
            bool result = false;

            RegisterableFilter filter = new RegisterableFilter
            {
                FilterInstance = new ProductFilterDuvelGreen2(),
                ParameterBag = null
            };
            QueryableFilterManager.Register(filter);

            IQueryable<Product> products = new MockProduct()
                .CreateMultipleProducts(3);

            var entities = products.AsQueryable();

            var toFilteredResult = entities.FilterWith<IProductFilter, Product>();//this will filter Duvel Green 2 so 2 results are returned.

            List<Product> filterdVouchers = toFilteredResult.ToList();

            result = _productRepository.AddMultipleProducts(filterdVouchers);

            Assert.IsTrue(result);
        }

        /// <summary>
        /// This will fillter duvel green 2 so only 0 and 1 are inserted in the db.
        /// </summary>
        [TestMethod]
        public void IntegrationTest_Transaction_AddEntitiesWithFilter_Performance()
        {
            bool result = false;

            RegisterableFilter filter = new RegisterableFilter
            {
                FilterInstance = new ProductFilterDuvelGreen2(),
                ParameterBag = null
            };
            QueryableFilterManager.Register(filter);

            IQueryable<Product> products = new MockProduct()
                .CreateMultipleProducts(5000);

            var entities = products.AsQueryable();

            var toFilteredResult = entities.FilterWith<IProductFilter, Product>();//this will filter Duvel Green 2 so 2 results are returned.

            List<Product> filterdVouchers = toFilteredResult.ToList();

            result = _productRepository.AddMultipleProducts(filterdVouchers);

            Assert.IsTrue(result);
        }

        /// <summary>
        /// This test demonstrates if you not register the filter or you disable a filter then you get normal result back.
        /// </summary>
        [TestMethod]
        public void IntegrationTest_Transaction_AddEntitiesWithoutFilter()
        {
            bool result = false;

            //QueryableFilterManager.Register(new ProductFilterDuvelGreen2());//filter is not registered so this filter will be ignored.

            IQueryable<Product> products = new MockProduct()
                .CreateMultipleProducts(3);

            var entities = products.AsQueryable();

            var toFilteredResult = entities.FilterWith<IProductFilter, Product>();

            List<Product> filterdVouchers = toFilteredResult.ToList();

            result = _productRepository.AddMultipleProducts(filterdVouchers);

            Assert.IsTrue(result);
        }

        [TestCleanup]
        public void TestCleanup()
        {
            _productRepository.Dispose();
        }
    }
}
